package com.money.tracker.common.handler;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.money.tracker.common.enums.IResponseEnum;
import com.money.tracker.common.exception.MoneyTrackerBizException;
import com.money.tracker.common.entity.rsp.IResponse;
import com.money.tracker.common.utils.ExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * <p>
 * 全局异常拦截器
 * <p>
 *
 * @author zhangshuai
 * &#064;@date 2024/09/21
 */
@Slf4j
@RestControllerAdvice
public class MoneyTrackerExceptionHandler {

    /**
     * 权限码异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(NotPermissionException.class)
    public IResponse handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        ExceptionUtil.print(e);
        log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
        return IResponse.fail(IResponseEnum.NOT_PERMISSION);
    }

    /**
     * 参数校验异常
     *
     * @param methodArgumentNotValidException
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public IResponse throwCustomException(MethodArgumentNotValidException methodArgumentNotValidException) {
        log.error("[ @Vaild异常捕获 ] {}" , methodArgumentNotValidException);
        ExceptionUtil.print(methodArgumentNotValidException);
        return IResponse.fail(methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * 角色权限异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(NotRoleException.class)
    public IResponse handleNotRoleException(NotRoleException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage());
        ExceptionUtil.print(e);
        return IResponse.fail(IResponseEnum.NOT_PERMISSION);
    }

    /**
     * 认证失败
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = NotLoginException.class)
    public IResponse handleNotLoginException(NotLoginException e) {
        log.error("认证失败'{}',无法访问系统资源", e.getMessage());
        ExceptionUtil.print(e);
        return IResponse.fail(IResponseEnum.UNAUTHORIZED);
    }

    /**
     * 请求格式异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public IResponse handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
                                                         HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
        ExceptionUtil.print(e);
        return IResponse.fail(e.getMessage());
    }

    /**
     * 主键或UNIQUE索引，数据重复异常
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public IResponse handleDuplicateKeyException(DuplicateKeyException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',数据库中已存在记录'{}'", requestURI, e.getMessage());
        return IResponse.fail("数据库中已存在该记录，请联系管理员确认");
    }

    /**
     * Mybatis系统异常 通用处理
     */
    @ExceptionHandler(MyBatisSystemException.class)
    public IResponse handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        String message = e.getMessage();
        ExceptionUtil.print(e);
        if (message.contains("CannotFindDataSourceException")) {
            log.error("请求地址'{}', 未找到数据源", requestURI);
            return IResponse.fail("未找到数据源，请联系管理员确认");
        }
        log.error("请求地址'{}', Mybatis系统异常", requestURI, e);
        return IResponse.fail(message);
    }


    /**
     * 自定义异常出错
     *
     * @param e
     * @return
     */

    @ExceptionHandler(value = MoneyTrackerBizException.class)
    public IResponse handleEcDaqBizException(MoneyTrackerBizException e) {
        ExceptionUtil.print(e);
        return IResponse.fail(e.getMessage());
    }

    @ExceptionHandler(value = Exception.class)
    public IResponse handleException(Exception e) {
        ExceptionUtil.print(e);
        return IResponse.fail("系统出错,请稍后再试");
    }

}
